﻿#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtSerialPort/QSerialPortInfo>
#include <QDebug>
#include <QComboBox>
#include <QTextCodec>
#include <QStandardItemModel>
#include <QDateTime>
#include <QFile>
#include <QFileDialog>
#include <QMessageBox>
#include <QTextStream>
#include <QThread>



//CRC校验
unsigned int calccrc(unsigned char crcbuf, unsigned int crc)
{
    unsigned char i;

    crc = crc ^ crcbuf;

    for (i = 0; i < 8; i++)
    {
        unsigned char chk;
        chk = crc & 1;
        crc = crc >> 1;
        crc = crc & 0x7fff;
        if (chk == 1)
            crc = crc ^ 0xa001;
        crc = crc & 0xffff;
    }
    return crc;
}




void MainWindow::ByteToHexString(QString &str, QByteArray &ba)
{
    QString strs = ba.toHex().toUpper();//直接转换中间没有空格
    for(int i=0;i<strs.length();i+=2)
    {
        QString str_1 = strs.mid (i,2);
        str += str_1;
        str += " ";
    }
}


//CRC校验 指针
unsigned int chkcrc(unsigned char *buf, unsigned char len)
{
    unsigned char hi, lo;
    unsigned int i;
    unsigned int crc;
    crc = 0xFFFF;
    for (i = 0; i < len; i++)
    {
        crc = calccrc(*buf, crc);
        buf++;
    }

    hi = crc % 256;
    lo = crc / 256;
    crc = (hi << 8) | lo;
    return crc;
}

//CRC校验 数组
uint crc16_modbus(QByteArray modbusdata, uint length)
{
    uint i, j;
    uint crc16 = 0xffff;
    for (i = 0; i < length; i++)
    {
        crc16 ^= modbusdata[i];
        for (j = 0; j < 8; j++)
        {
            if ((crc16 & 0x01) == 1)
            {
                crc16 = (crc16 >> 1) ^ 0xA001;
            }
            else
            {
                crc16 = crc16 >> 1;
            }
        }
    }
    return crc16;
}

// char 转为 16进制
char convertCharToHex(char ch)
{
    /*
    0x30等于十进制的48，48也是0的ASCII值，，
    1-9的ASCII值是49-57，，所以某一个值－0x30，，
    就是将字符0-9转换为0-9
    */
    if((ch >= '0') && (ch <= '9'))
        return ch-0x30;
    else if((ch >= 'A') && (ch <= 'F'))
        return ch-'A'+10;
    else if((ch >= 'a') && (ch <= 'f'))
        return ch-'a'+10;
    else return (-1);
}

//Qstring 转为 16进制的函数
void convertStringToHex(const QString &str, QByteArray &byteData)
{
    int hexdata,lowhexdata;
    int hexdatalen = 0;
    int len = str.length();
    byteData.resize(len/2);
    char lstr,hstr;
    for(int i=0; i<len; )
    {
        //char lstr,
        hstr=str[i].toLatin1();
        if(hstr == ' ')
        {
            i++;
            continue;
        }
        i++;
        if(i >= len)
            break;
        lstr = str[i].toLatin1();
        hexdata = convertCharToHex(hstr);
        lowhexdata = convertCharToHex(lstr);
        if((hexdata == 16) || (lowhexdata == 16))
            break;
        else
            hexdata = hexdata*16+lowhexdata;
        i++;
        byteData[hexdatalen] = (char)hexdata;
        hexdatalen++;
    }
    byteData.resize(hexdatalen);
}


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    init();

    m_serialPort = new QSerialPort();
    m_portNameList = getPortNameList();
    ui->comboBoxPortName->addItems(m_portNameList);

    ui->comboBoxBaudRate->setCurrentIndex(2);

    m_analysis = new analysis();


    //如果串口错误发出错误信号，并执行对应的槽函数
//    connect(m_serialPort, static_cast<void(QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error),
//          [=](QSerialPort::SerialPortError error){
//              errorOccurredqq(error);
//    });

    connect(m_serialPort,static_cast<void(QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error)
            ,this,&MainWindow::handleSerialError);

    connect(m_serialPort,&QSerialPort::readyRead,[=](){
        readyReads();
    });

   // connect(m_serialPort,SIGNAL(readyRead()),this,SLOT(readyReads()));

    connect(ui->Flush_UART,&QPushButton::clicked,this,&MainWindow::UART_Flush_SLOTS);//刷新可用串口
    connect(m_analysis,&analysis::analysis_over,this,&MainWindow::sendBackMsg,Qt::QueuedConnection);
    connect(m_analysis,&analysis::toUishowMsgPack,this,&MainWindow::ShowMsgQByteArray,Qt::QueuedConnection);
    connect(m_analysis,&analysis::toUishowMsg,this,&MainWindow::ShowMsgString,Qt::QueuedConnection);
    connect(m_analysis,&analysis::wirtTablec,this,&MainWindow::wirtTablec,Qt::QueuedConnection);
    connect(m_analysis,&analysis::wirtTabler,this,&MainWindow::wirtTabler,Qt::QueuedConnection);
    connect(this,&MainWindow::Start,m_analysis,&analysis::ParseResponseMessage,Qt::QueuedConnection);
    connect(ui->btnOpenCOM,&QPushButton::clicked,this,&MainWindow::PortButton);

}


//主线程初始化
void MainWindow::init()
{
    serialPortStatus = new int(0);
    //显示当前时间
    m_timer = new QTimer(this);
    rcvDataTimer = new QTimer(this);
    m_serialPort = new QSerialPort();

    m_timer->setInterval(1000);
    m_timer->start();

    connect(m_timer, SIGNAL(timeout()), this, SLOT(showtime()));
    //设置定时时间，精确定时
    rcvDataTimer->setInterval(20);
    rcvDataTimer->setTimerType(Qt::PreciseTimer);
    //读取数据的时间
    connect(rcvDataTimer,&QTimer::timeout,this,&MainWindow::timerOut);

    readyReads();

    //限制从机地址
    connect(ui->slaveadd_Edit,&QLineEdit::textChanged,[=](){
        if(ui->slaveadd_Edit->text().toInt()>247||ui->slaveadd_Edit->text().toInt()<1)
        {
            QMessageBox::warning(this,"提示","请检查从机地址是否合法！",QMessageBox::Ok,QMessageBox::NoButton);
            ui->slaveadd_Edit->clear();
        }
    });

    //表格初始化
    tableInit();
    readseting = new QSettings("Data.ini", QSettings::IniFormat);
    iniReadDate();
}

//表格初始化
void MainWindow::tableInit()
{
    //设置表格
    QStringList TableHeader;
    TableHeader << "地址" << "数据";
    ui->table_coil->setVerticalHeaderLabels(TableHeader);
    ui->table_coil->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->tableregs->setVerticalHeaderLabels(TableHeader);
    ui->tableregs->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->tableregs->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->table_coil->setEditTriggers(QAbstractItemView::NoEditTriggers);
}
//将ini文件中的数据放进表格
void MainWindow::iniReadDate()
{
    for(int i = 0; i < (65536); i++)
    {
        //地址设置
        QString adr =  "0X" + QString("%1").arg(i,4,16,QLatin1Char('0'));
        ui->table_coil->setItem(0,i, new QTableWidgetItem(QString(adr).toUpper()));
        ui->table_coil->item(0,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
        ui->tableregs->setItem(0,i, new QTableWidgetItem(QString(adr)));
        ui->tableregs->item(0,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
        //读出线圈数据
        QString coilData = readseting->value("Section" + QString::number(i+1) + "/coil").toString();
        //读出寄存器数据
        QString registerData = readseting->value("Section" + QString::number(i+1) + "/regi").toString();
        //在线圈数据表中显示数据
        ui->table_coil->setItem(1,i,new QTableWidgetItem(coilData));
        //设置表格内文字水平+垂直对齐
        ui->table_coil->item(1,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
        //在寄存器数据表中显示数据
        ui->tableregs->setItem(1,i,new QTableWidgetItem(registerData));
        //设置表格内文字水平+垂直对齐
        ui->tableregs->item(1,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    }
}
//更新线圈表
void MainWindow::wirtTablec(quint16 num, quint16 satrtaddr, QString bac)
{
    ui->table_coil->blockSignals(true);
    for(int i = satrtaddr,k=0; k < num;k++,i++)
    {
        //在线圈数据表中显示数据
        QString data;
        if(bac[k] == '1')
        {
            data ="1";
        }
        else
        {
            data ="0";
        }
        ui->table_coil->setItem(1,i,new QTableWidgetItem(data));
        ui->table_coil->item(1,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    }
    ui->table_coil->blockSignals(false);
    bac.clear();
}

//更新寄存器表
void MainWindow::wirtTabler(quint16 num, quint16 satrtaddr,QVector<quint16> bar)
{
    ui->tableregs->blockSignals(true);
    for(int i = satrtaddr,k=0; k < num;k++,i++)
    {
        ui->tableregs->setItem(1,i,new QTableWidgetItem(QString("%1").arg(bar[k])));
        ui->tableregs->item(1,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    }
    ui->tableregs->blockSignals(false);
    bar.clear();
}

//显示信息
void MainWindow::showmsg(QString msg)
{
    ui->txtReceiveData->append(msg+"\r\n");
}

//显示时间槽函数
void MainWindow::showtime()
{
    QDateTime current_date_time =QDateTime::currentDateTime();
    QString current_date =current_date_time.toString("yyyy.MM.dd hh:mm:ss ddd");
    ui->time->setText(current_date);
}

//主窗口析构
MainWindow::~MainWindow()
{
    if (m_serialPort->isOpen())
    {
        m_serialPort->close();
    }
    delete m_serialPort;

    delete ui;
}

QStringList MainWindow::getPortNameList()
{
    QStringList m_serialPortName;
    foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {
        m_serialPortName << info.portName();
        qDebug()<<"serialPortName:"<<info.portName();
    }
    return m_serialPortName;
}


//串口发生错误 槽函数
void MainWindow::UART_eerom_SLOTS(int y )
{
        if(y!=0)//错误0 表示没有错误
        {
            int int_eeorm=Uart_Objects.error();//获取错误数据
            QString eerom1;//创建一个字符串
            switch (int_eeorm)
            {
                 case 1 : eerom1 = " 试图打开不存在的设备时发生错误。";   break;
                 case 2 : eerom1 = " 当另一个进程或用户没有足够的权限和凭据打开一个已经打开的设备时发生错误。";   break;
                 case 3 : eerom1 = " 试图打开此对象中已经打开的设备时发生错误。";   break;
                 case 4 : eerom1 = " 读取数据时由硬件检测到的奇偶校验错误。该值过时。我们强烈建议不要在新代码中使用它。";   break;
                 case 5 : eerom1 = " 读取数据时由硬件检测到的帧错误。该值过时。我们强烈建议不要在新代码中使用它。";   break;
                 case 6 : eerom1 = " 由硬件在输入线上检测到的中断状态。该值过时。我们强烈建议不要在新代码中使用它。";   break;
                 case 7 : eerom1 = " 写入数据时发生了一个I/O错误。";   break;
                 case 8 : eerom1 = " 读取数据时发生了一个I/O错误。";   break;
                 case 9 : eerom1 = " 一个I/O错误发生时，资源变得不可用，例如当设备被意外地从系统中删除。";   break;
                 case 10 : eerom1 = " 正在运行的操作系统不支持或禁止请求的设备操作。";   break;
                 case 11 : eerom1 = " 发生了一个未知的错误。";   break;
                 case 12 : eerom1 = " 发生超时错误。";   break;
                 case 13 : eerom1 = " 当执行的操作只有打开设备才能成功执行时，发生此错误。";   break;
            }
             QMessageBox::about(this,tr("串口打开失败"),eerom1 );//弹出提示框，并显示错误信息
        }
}

//错误处理
void MainWindow::errorOccurredqq(QSerialPort::SerialPortError error)
{
    switch ((int)error)
    {
    case 0:
      /* 没有错误 */
      openSucess(true);
      break;
    case 1:
      /* 打开一个不存在的设备 */
      m_serialPort->close();
      errorOccurred(QString("打开一个不存在的设备!"));
      openSucess(false);
      break;
    case 2:
      /* 无权限打开一个 */
      m_serialPort->close();
      errorOccurred(QString("无权限打开设备!"));
      openSucess(false);
      break;
    case 3:
      /* 打开一个已经打开的设备 */
      errorOccurred(QString("设备已打开!"));
      openSucess(false);
      break;
    case 7:
      /* 写入数据时发生的i/o错误 */
      m_serialPort->close();
      errorOccurred(QString("写数据错误!"));
//      openUart();
      break;
    case 8:
      /* 读取数据时发生了i/o错误 */
      m_serialPort->close();
      errorOccurred(QString("读数据错误!"));
//      openUart();
      break;
    case 9:
      /* 设备意外拔出,会发生i/o错误 */
      m_serialPort->close();
      errorOccurred(QString("串口已拔出!"));
        openSucess(false);
      break;
    case 10:
      /* 系统不支持或者禁止的操作 */
      break;
    case 11:
      /* 未知错误 */
      m_serialPort->close();
       errorOccurred(QString("发生未知错误!"));
      openSucess(false);
      break;
    }
}

//判断串口标志
void MainWindow::openSucess(bool sucess)
{
    if (sucess == true)
    {
        uartIsOpen = true;
    } else
    {
        uartIsOpen = false;
    }
}


//串口错误处理
void MainWindow::errorOccurred(QString error)
{
    if (false == error.isEmpty())
    {
        QMessageBox::information(this, "串口错误", error);
    }
}

//刷新可用串口槽函数
void MainWindow::UART_Flush_SLOTS( )
{
//   ui->comboBoxPortName->clear();//清除下拉列表框内容
//   uart_info = QSerialPortInfo::availablePorts();//获取系统可用的串口
//   qDebug()<< "系统可用串口数量为 "<<uart_info.count(); //输出系统可用串口数量（链表中的数量）

//   for (int i=0;i<uart_info.count();i++)
//   ui->comboBoxPortName->addItem(uart_info.value(i).portName()); //不带图

    ui->comboBoxPortName->clear();
    //通过QSerialPortInfo查找可用串口
    foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {   //在portBox中显示可用串口
        ui->comboBoxPortName->addItem(info.portName());
    }
}


//打开串口槽函数
//void MainWindow::on_btnOpenCOM_clicked()
//{
//        //m_serialPort->open(QIODevice::ReadWrite);
//        ui->comboBoxBaudRate->setEnabled(false);
//        ui->data_bit_comboBox->setEnabled(false);
//        ui->verify_comboBox->setEnabled(false);
//        ui->stop_comboBox->setEnabled(false);
//        ui->comboBoxPortName->setEnabled(false);

////    connect(&Uart_Objects,&QSerialPort::errorOccurred,this,&MainWindow::UART_eerom_SLOTS);//串口出现错误

//    if (ui->btnOpenCOM->text()=="打开串口") {

//        //设置串口名字 假设我们上面已经成功获取到了 并且使用第一个
//        m_serialPort->setPortName(m_portNameList[ui->comboBoxPortName->currentIndex()]);

//        if(!m_serialPort->open(QIODevice::ReadWrite))//用ReadWrite 的模式尝试打开串口
//        {
//            qDebug()<<m_portNameList[ui->comboBoxPortName->currentIndex()]<<"打开失败!";
//            return;
//        }

//        //打开成功
//        m_serialPort->setBaudRate(ui->comboBoxBaudRate->currentText().toInt(),QSerialPort::AllDirections);//设置波特率和读写方向
//        m_serialPort->setDataBits(QSerialPort::Data8);              //数据位为8位
//        m_serialPort->setFlowControl(QSerialPort::NoFlowControl);   //无流控制
//        m_serialPort->setParity(QSerialPort::NoParity);             //无校验位
//        m_serialPort->setStopBits(QSerialPort::OneStop);            //一位停止位

//        //连接信号槽 当下位机发送数据QSerialPortInfo 会发送个 readyRead 信号,定义个槽void receiveInfo()解析数据

//        connect(m_serialPort,SIGNAL(readyRead()),this,SLOT(readyReads()));

//        ui->btnOpenCOM->setText("关闭串口");
//    } else {
//        ui->btnOpenCOM->setText("打开串口");
//    }
//}

void MainWindow::PortButton()
{
    //判断当前串口按钮状态，显示"打开串口"则进行打开操作，显示"关闭串口"则进行关闭操作
    if(ui->btnOpenCOM->text() == "关闭串口")
    {
        PortDisConnect();
        return;
    }

    //初始化串口配置参数结构体
    portParameters portPara;
    portStructInitialize(&portPara);
    //进行打开操作，成功返回true，失败返回false
    bool portSetStatus = PortConnect(&portPara);
    if(portSetStatus == true)
    {
        //调整串口状态为打开
        *serialPortStatus = 1;
        //调整按钮，输入框关闭，发送按钮打开，设置串口按钮为”关闭串口“
        boxConnect();
        //输出成功提示信息
        OpenSuccessPrompt();
    }
    else
    {
        //输出失败提示信息
        //OpenFailurePrompt();
    }

}

//2. 提示串口打开失败函数
void MainWindow::OpenFailurePrompt()
{
    QMessageBox::warning(this,"提示","串口打开失败！请检查串口！",QMessageBox::Ok);
    //时间
//    TimeInformation();
    //消息窗口显示信息
    ui->txtReceiveData->append("串口打开失败！请检查串口！");
}

void MainWindow::OpenSuccessPrompt()
{
    QMessageBox::information(this,"提示","串口打开成功！",QMessageBox::Ok);
    //时间
    //TimeInformation();
    //消息窗口显示信息
    ui->txtReceiveData->append("成功打开串口! 串口号：" + ui->comboBoxPortName->currentText());
}

void MainWindow::boxConnect()
{
    //本机地址、串口号、波特率、数据位、停止位、校验位的输入框关闭
    ui->slaveadd_Edit->setEnabled(false);
    ui->comboBoxPortName->setEnabled(false);
    ui->comboBoxBaudRate->setEnabled(false);
    ui->data_bit_comboBox->setEnabled(false);
    ui->stop_comboBox->setEnabled(false);
    ui->verify_comboBox->setEnabled(false);
    ui->Flush_UART->setEnabled(false);
    //设置串口按钮为”关闭串口“
    ui->btnOpenCOM->setText("关闭串口");
}

//4. 串口关闭函数
void MainWindow::PortDisConnect()
{
    //调整串口状态为关闭
    *serialPortStatus = 0;
    //清空缓存区
//    bufferArray.clear();
    //关闭串口、清除串口
    m_serialPort->clear();
    m_serialPort->close();
    //调整按钮，输入框打开，发送按钮关闭，设置串口按钮为”打开串口“
    boxDisconnect();
    //提示关闭串口信息
    ClosePortPrompt();

}

//3. 提示串口关闭函数
void MainWindow::ClosePortPrompt()
{
    QMessageBox::information(this,"提示","串口已关闭！",QMessageBox::Ok);
    //时间
    //TimeInformation();
    //消息窗口显示信息
    ui->txtReceiveData->append("已关闭串口：" + ui->comboBoxPortName->currentText());
}


//2. 输入框开启，串口按钮设置为打开函数
void MainWindow::boxDisconnect()
{
    //本机地址、串口号、波特率、数据位、停止位、校验位的输入框打开
    ui->slaveadd_Edit->setEnabled(true);
    ui->comboBoxPortName->setEnabled(true);
    ui->comboBoxBaudRate->setEnabled(true);
    ui->data_bit_comboBox->setEnabled(true);
    ui->stop_comboBox->setEnabled(true);
    ui->verify_comboBox->setEnabled(true);
    ui->Flush_UART->setEnabled(true);
    //设置串口按钮为”打开串口“
    ui->btnOpenCOM->setText("打开串口");
}


//3. 串口连接函数
bool MainWindow::PortConnect(portParameters *structPt)
{
    //设置串口号
    m_serialPort->setPortName(structPt->portNumber);

    //如果打开失败则返回false
    if(!m_serialPort->open(QIODevice::ReadWrite))
    {
        return false;
    }

    //如果打开成功，则设置波特率、数据位、停止位、校验位
    //波特率
    m_serialPort->setBaudRate(structPt->baudRate);

    //数据位
    m_serialPort->setDataBits(structPt->dataBits);

    //停止位
    m_serialPort->setStopBits(structPt->stopBits);

    //校验位
    m_serialPort->setParity(structPt->parity);

    //流控制
    m_serialPort->setFlowControl(QSerialPort::NoFlowControl);

    return true;
}

//2. 串口参数结构体初始化函数
void MainWindow::portStructInitialize(portParameters *structPt)
{
    //设置本机地址
    if(ui->slaveadd_Edit->text() == NULL)
    {
        structPt->localAddress = 1;
    }
    else
    {
        structPt->localAddress = ui->slaveadd_Edit->text().toInt();
    }
    structPt->portNumber = ui->comboBoxPortName->currentText();       //串口号

    //设置波特率、数据位、停止位、校验位
    //波特率
    switch (ui->comboBoxBaudRate->currentIndex())
    {
    case 0:
    {
        structPt->baudRate = QSerialPort::Baud9600;
        *baudRate = 9600;
        break;
    }
    case 1:
    {
        structPt->baudRate = QSerialPort::Baud19200;
        *baudRate = 19200;
        break;
    }
    case 2:
    {
        structPt->baudRate = QSerialPort::Baud115200;
        *baudRate = 115200;
        break;
    }
    default:
        break;
    }

    //数据位
    switch (ui->data_bit_comboBox->currentIndex())
    {
    case 0:
    {
        structPt->dataBits = QSerialPort::Data5;
        break;
    }
    case 1:
    {
        structPt->dataBits = QSerialPort::Data6;
        break;
    }
    case 2:
    {
        structPt->dataBits = QSerialPort::Data7;
        break;
    }
    case 3:
    {
        structPt->dataBits = QSerialPort::Data8;
        break;
    }
    default:
        break;
    }

    //停止位
    switch (ui->stop_comboBox->currentIndex())
    {
    case 0:
    {
        structPt->stopBits = QSerialPort::OneStop;
        break;
    }
    case 1:
    {
        structPt->stopBits = QSerialPort::TwoStop;
        break;
    }
    default:
        break;
    }

    //校验位
    switch (ui->verify_comboBox->currentIndex())
    {
    case 0:
    {
        structPt->parity = QSerialPort::NoParity;
        break;
    }
    case 1:
    {
        structPt->parity = QSerialPort::OddParity;
        break;
    }
    case 2:
    {
        structPt->parity = QSerialPort::EvenParity;
        break;
    }
    default:
        break;
    }
}


//void MainWindow::on_btnOpenCOM_clicked()
//{
//    connect(&Uart_Objects,&QSerialPort::errorOccurred,this,&MainWindow::UART_eerom_SLOTS);//串口出现错误
//    connect(&Uart_Objects,SIGNAL(readyRead()),this,SLOT(readyReads()));
//    ui->comboBoxBaudRate->setEnabled(false);
//    ui->data_bit_comboBox->setEnabled(false);
//    ui->verify_comboBox->setEnabled(false);
//    ui->stop_comboBox->setEnabled(false);
//    ui->comboBoxPortName->setEnabled(false);
//    switch (ui->data_bit_comboBox->currentIndex()  ){//数据位
//      case 0: Uart_Objects.setDataBits(QSerialPort::Data8); break;
//      case 1: Uart_Objects.setDataBits(QSerialPort::Data7); break;
//      case 2: Uart_Objects.setDataBits(QSerialPort::Data6); break;
//      case 3: Uart_Objects.setDataBits(QSerialPort::Data5);break;
//      default: break;
//    }

//    switch (ui->verify_comboBox->currentIndex()  ){//校验位
//      case 0: Uart_Objects.setParity(QSerialPort::NoParity);      break;
//      case 1: Uart_Objects.setParity(QSerialPort::EvenParity);    break;
//      case 2: Uart_Objects.setParity(QSerialPort::OddParity);     break;
//      case 3: Uart_Objects.setParity(QSerialPort::SpaceParity);   break;
//      case 4: Uart_Objects.setParity(QSerialPort::MarkParity);    break;
//      case 5: Uart_Objects.setParity(QSerialPort::UnknownParity); break;
//    default: break;
//    }

//    switch (ui->stop_comboBox->currentIndex()  ){//停止位
//      case 0: Uart_Objects.setStopBits(QSerialPort::OneStop); break;
//      case 1: Uart_Objects.setStopBits(QSerialPort::OneAndHalfStop); break;
//      case 2: Uart_Objects.setStopBits(QSerialPort::TwoStop); break;
//      case 3: Uart_Objects.setStopBits(QSerialPort::UnknownStopBits);break;
//      default: break;
//    }

//    Uart_Objects.setPortName(ui->comboBoxPortName->currentText());//根据下拉框显示的内容  确定打开的串口
//    switch (ui->comboBoxBaudRate->currentIndex()  ){//选择波特率
//      case 0: Uart_Objects.setBaudRate(QSerialPort::Baud115200); break;
//      case 1: Uart_Objects.setBaudRate(QSerialPort::Baud57600 ); break;
//      case 2: Uart_Objects.setBaudRate(QSerialPort::Baud38400 ); break;
//      case 3: Uart_Objects.setBaudRate(QSerialPort::Baud19200 ); break;
//      case 4: Uart_Objects.setBaudRate(QSerialPort::Baud9600  ); break;
//      case 5: Uart_Objects.setBaudRate(QSerialPort::Baud4800  ); break;
//      case 6: Uart_Objects.setBaudRate(QSerialPort::Baud2400  ); break;
//      case 7: Uart_Objects.setBaudRate(QSerialPort::Baud1200  ); break;
//      default: break;
//    }

//    if(Uart_Objects.open(QIODevice::ReadWrite)==false)//打开串口
//    {
//       ui->sign_label->setText("串口打开失败");
//       UART_RUN = false;//打开失败 标志位清零
//    }else
//    {
//        ui->sign_label->setText("串口打开");
//        UART_RUN = true;//打开成功 标志位置1
//    }
//}

//void MainWindow::on_closebtn_clicked()
//{
//    m_serialPort->close();
//    ui->sign_label->setText("串口未打开");
//    ui->comboBoxBaudRate->setEnabled(true);
//    ui->data_bit_comboBox->setEnabled(true);
//    ui->verify_comboBox->setEnabled(true);
//    ui->stop_comboBox->setEnabled(true);
//    ui->comboBoxPortName->setEnabled(true);
//}


//5. 串口断开检测函数
void MainWindow::handleSerialError(QSerialPort::SerialPortError error)
{
    if (error == QSerialPort::ResourceError)
    {
        QMessageBox::critical(this,"Error","串口连接中断，请检查是否正确连接！");
        //时间
        //TimeInformation();
        //消息窗口显示信息
        ui->txtReceiveData->append("串口连接中断，请检查是否正确连接！");
        PortDisConnect();
    }
}


//读取完向主线程发送信号
void MainWindow::timerOut()
{
    if(sendArray.isEmpty())
        return;
    rcvDataTimer->stop();
    receiveInfo();
    emit Start(sendArray,m_addr);
    sendArray.clear();
}

//返回读取缓冲时间
int MainWindow::ReceivingTime()
{
    //RTU报文最大长度
    double maxMessageLength = 256;
    //当前波特率
    double currentBaudRate = *baudRate;
    //计算读取缓冲时间
    int recTime = (8*maxMessageLength*1000/currentBaudRate);
    //返回读取缓冲时间
    return recTime;
}

void MainWindow::readyReads()
{
    QByteArray info = m_serialPort->readAll();
    emit Start(sendArray,m_addr);
    qDebug() << info.toHex();
    if(rcvDataTimer->isActive())
    {
        rcvDataTimer->stop();
    }
    if(true==info.isEmpty())
        return;
    sendArray += info;
    rcvDataTimer->start(50);
}

//接收的数据并进行解析
void MainWindow::receiveInfo()
{
    QByteArray info = m_serialPort->readAll();
    QDateTime current_date_time =QDateTime::currentDateTime();
    QString current_date =current_date_time.toString("yyyy.MM.dd hh:mm:ss");

    QString strReceiveData = "";

    if(ui->checkBoxHexReceive->isChecked()) //判断是否选择16进制
    {
        QByteArray hexData = sendArray.toHex();
        strReceiveData = hexData.toUpper();

        qDebug()<<"接收到串口数据: "<<strReceiveData;

        //将接收的数据遍历加入空格
        for(int i=0; i<strReceiveData.size(); i+=2+1)
            strReceiveData.insert(i, QLatin1String(" "));
        strReceiveData.remove(0, 1);

        qDebug()<<"处理后的串口数据: "<<strReceiveData;

        ui->txtReceiveData->append(strReceiveData+" "+"<--主机发送"+" "+current_date+"\r\n");     //接收串口数据

        //emit Start(sendArray,m_addr);

    }
    else
    {
        strReceiveData = sendArray;
        //避免中文乱码
        QTextCodec *tc = QTextCodec::codecForName("GBK");
        QString tmpQStr = tc->toUnicode(sendArray);
        ui->txtReceiveData->append(tmpQStr);
    }
}

//显示异常信息
void MainWindow::ShowMsgString(QString error)
{
    ui->txtReceiveData->append(error);
    ui->txtReceiveData->moveCursor(QTextCursor::End);
}

//显示回应报文
void MainWindow::ShowMsgQByteArray(QByteArray ba)
{
    QString str;
    ByteToHexString(str,ba);
    ui->txtReceiveData->append("回应报文\r\n"+str);
    ui->txtReceiveData->moveCursor(QTextCursor::End);
}


//清屏槽函数
void MainWindow::on_clearButton_clicked()
{
    ui->txtReceiveData->clear();
}

//发送数据槽函数
void MainWindow::sendBackMsg(QByteArray msg)
{
    m_serialPort->write(msg);
}

//确定从机地址
void MainWindow::on_pushButton_clicked()
{
    m_addr = ui->slaveadd_Edit->text().toInt();
    QMessageBox::StandardButton open;
    open = QMessageBox::question(this,"提示","确认从机地址？",QMessageBox::Yes | QMessageBox::No,QMessageBox::No);
}


void MainWindow::on_historyBtn_clicked()
{
    QString fileName=QFileDialog::getSaveFileName(this,"Save File",QDir::currentPath());
    if(fileName.isEmpty())
    {
        QMessageBox::information(this,"Error Message","请选择文件的路径");
        return;
    }

    QFile *file=new QFile;
    file->setFileName(fileName);
    bool ok=file->open(QIODevice::WriteOnly);
    if(ok)
    {
        QTextStream out(file);
        out<<ui->txtReceiveData->toPlainText();
        file->close();
        delete file;
    }
    else
    {
        QMessageBox::information(this,"Error Messaage","File Save Error"+file->errorString());
        return;
    }
}
